package com.supreme.cacheserver.service;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.benmanes.caffeine.cache.Cache;
import com.supreme.cacheserver.annotation.DoubleCache;
import com.supreme.commonentity.mysql.primary.MBTest;
import com.supreme.commonmybatis.mapper.TestMapper;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

@Service
public class TestService {

    @Resource
    private TestMapper testMapper;

    @Resource
    private Cache<String, Object> caffeineCache;

    @Resource
    private Cache<String, MBTest> caffeineCacheItem;

    @Resource
    private Cache<String, List<MBTest>> caffeineCacheList;

    @Resource
    private RedisTemplate<String, MBTest> redisTemplate;

    public List<MBTest> selectCacheTest() {
        Object listObject = caffeineCache.get(MBTest.cacheKey("ALL"), new Function<String, List<MBTest>>() {
            @Override
            public List<MBTest> apply(String cacheKey) {
                return testMapper.selectList(Wrappers.emptyWrapper());
            }
        });

        if (listObject instanceof List) {
            List<MBTest> testList = new ArrayList<>();
            for (Object itemObject : (List<?>) listObject) {
                testList.add((MBTest) itemObject);
            }
            return testList;
        }

        return null;
    }

    public MBTest selectCacheTestOne(Long testId) {
        return caffeineCacheItem.get(MBTest.cacheKey(testId), cacheKey -> {
            System.out.println("cacheKey: " + cacheKey);
            return testMapper.selectById(testId);
        });
    }

    public List<MBTest> selectCacheTestList() {
        return caffeineCacheList.get(MBTest.cacheKey("LIST"), cacheKey -> {
            System.out.println("cacheKey: " + cacheKey);
            return testMapper.selectList(Wrappers.emptyWrapper());
        });
    }

    @DoubleCache
    @Cacheable(value = "MBTest", key = "#testId")
    public MBTest selectCacheableTestOne(Long testId) {
        return testMapper.selectOne(Wrappers.lambdaQuery(MBTest.class).eq(MBTest::getId, testId));
    }

    @DoubleCache(cache = true)
    @Cacheable(value = "MBTest")
    public List<MBTest> selectCacheableTestList() {
        return testMapper.selectList(Wrappers.lambdaQuery(MBTest.class).orderByDesc(MBTest::getId));
    }

    @CacheEvict(value = "MBTest", allEntries = true)
    public int createCacheableTestOne(MBTest test) {
        return testMapper.insert(test);
    }

//    @CachePut(value = "CACHE_TEST", key = "#test.id")
    @CacheEvict(value = "MBTest", key = "#test.id", allEntries = true)
    public int updateCacheableTestOne(MBTest test) {
        return testMapper.updateById(test);
    }

    @CacheEvict(value = "MBTest", key = "#testId", allEntries = true)
    public int deleteCacheableTestOne(Long testId) {
        return testMapper.deleteById(testId);
    }

    public void insertTestListToRedis(String key, List<MBTest> testList) {
        redisTemplate.opsForList().rightPushAll(key, testList);
    }

    public List<MBTest> getTestListFromRedis(String key) {
        return redisTemplate.opsForList().range(key, 0, -1);
    }
}
